#include "lib/includes.h"
#include "cputest.h"
//变量定义

U32 APP_CardBlock(void)
{
	U32 rcode =0 ;
	U08 Buffer[4];
	//锁卡操作
	// rcode =ICF_SelectSFI( "\x3F\x00", Gich_Icc );
	// if( rcode != 0x9000 )
	// { return 1; }
	// rcode = ICF_SelectSFI( "\xDF\x01", Gich_Icc );  
	// if( rcode != 0x9000 )
	// { return 1; }
	// rcode =ICF_SelectSFI( "\xDF\x01", Gich_Sam );
	// if( rcode != 0x9000 )
	// { return 1;	}

	if( ICF_GetChallenge4B( Buffer, Gich_Icc) != 0x9000 )
	{ DEF_SysCard_Debug ;return 1; }					  				//获取随机数

   	rcode = ICF_InitSamForDes(Gich_Sam);
	if(rcode != 0x9000)
	{ DEF_SysCard_Debug ;return 1; }
	if( ICF_SamDESCrypt( Buffer, Gich_Sam ) == 0x9000 )
	{
	   Buffer[0] = gpRcvBuffer[0]; 
       Buffer[1] = gpRcvBuffer[1];		 
       Buffer[2] = gpRcvBuffer[2];	 
       Buffer[3] = gpRcvBuffer[3];					// 随机数
	}

	rcode =ICF_CardBlock( 0x04, Buffer,Gich_Icc);
	if( rcode != 0x9000 )
	{ DEF_SysCard_Debug ;return 1; }
    return 0;
}
U32 APP_ADV_FindBlacklist_cpu( U08 *pBlacklist )
{
	U08 buf[12];
	
	buf[0] = 0;
	memcpy( &buf[1], pBlacklist, 8 ); 

	printf("->CardASN:%02x%02x%02x%02x%02x%02x%02x%02x\n",pBlacklist[0],pBlacklist[1]
		,pBlacklist[2],pBlacklist[3],pBlacklist[4],pBlacklist[5],pBlacklist[6],pBlacklist[7]);

	if( APP_FindBlacklist( DEF_BlkMoryBank_Black01, (buf+1), buf, NCAP_BlacklistBuffer ) == 0 )
	{														//找到了卡号
		if( buf[0] == 0 )									//并且状态还一样的	
		 { 
			//APP_WriteRec_Blacklist( DEF_RecMoryBank_Black01, TradeInformation.CardASN );	
			printf("<-ok,find Blacklist!\n");
			//锁卡	
			if(APP_CardBlock() == 0)
			{ printf("Block card ok!\n");}
			else
			{ printf("Block card fail!\n");}		
			return 0;	
		 }									
		return 1; 
	}
	else
	{
		printf("<-not find Blacklist!\n");		
	}
	return 2;
}
/*
**************************************************************************************************************
*
* 函数原型：void APP_WriteRec_CpuRec( U32 id, U32 recstat )
*
* 函数功能：CPU卡消费记录保存处理
*
* 函数输入：id			存储的文件ID号
*			recstat		记录状态，1=正常，2=灰色，3=MAC错误
*			stat 		逃票状态，0：正常，非0：逃票
*
* 函数输出：无
*
* 函数返回：无
*   
**************************************************************************************************************
*/
void APP_WriteRec_CpuRec( U32 id, U32 recstat, U32 stat )
{
	U32 rcode,recsn,pyhsn,i;
	U08 buf[DEF_FLASH_MaxRecLength];							//这里有问题的

	memset( buf, 0, DEF_FLASH_MaxRecLength );					//将所有缓冲区写全0
//=====================================>> 记录组帧
	rcode = APP_Get_RecFileNO( id, &pyhsn, &recsn );			//获取最后一条记录的流水号错误，
	if( rcode != 0 ) 											//写记录失败，失败处理
	{ goto ER_Pro; }
	pyhsn++;
	buf[0] = ( pyhsn >> 24 );
	buf[1] = ( pyhsn >> 16 );
	buf[2] = ( pyhsn >> 8 );
	buf[3] = pyhsn;												//记录的前4字节存储记录流水号

	buf[4] = DEF_RecType_Trade;									//记录类型 消费记录

	memcpy( &buf[5],  gSamAppInfo.PsamTID, 6 );					//POS编号
	memcpy( &buf[11], DealCfg.CircuitryID, 2 );					//线路标识
	memcpy( &buf[13], TradeInformation.DealTime, 7 );			//交易时间
	memcpy( &buf[20], buf, 4 );									//记录流水号

	if( stat != 0 ) 		//分段收费逃票
	{ memcpy( &buf[24], CPUM1_BillInfo.MotoEmpID, 3 ); }
	else
	{ memcpy( &buf[24], OthCfg.MotoEmpID, 3 ); }					//司机卡empID

	memcpy( &buf[27], CPU_CommInfo.CounterSn, 4 );  			//用户帐号
	memcpy( &buf[31], TradeInformation.CardASN, 8 );  			//卡应用序列号
	buf[39] = CPU_CommInfo.HolderCardSn;						//持卡序号
	buf[40] = 2;												//卡类别 1 M1卡，2 CPU卡
	memcpy( &buf[41], SysCfg.AppCityID, 2 );					//交易地城市代码
	memcpy( &buf[43], TradeInformation.CityCode, 2 );			//卡所属地城市代码

	buf[45] = TradeInformation.PullCTC[0];
	buf[46] = TradeInformation.PullCTC[1]; 						//消费交易前计数器

	buf[47] = ( TradeInformation.OldPurseBalance >> 24 );		//用户卡交易前余额
	buf[48] = ( TradeInformation.OldPurseBalance >> 16 );
	buf[49] = ( TradeInformation.OldPurseBalance >>  8 );
	buf[50] = ( TradeInformation.OldPurseBalance >>  0 );

	buf[51] = ( TradeInformation.DealMoney >> 8 );				//用户卡交易金额
	buf[52] = TradeInformation.DealMoney;

	if( ( DealCfg.TimePriceStat != 0 ) || ( stat != 0 ) )		//分段收费模式
	{ buf[53] = 0x40; }
	else	
	{ buf[53] = 0x00; }											//交易应用类型（测试标记）

	buf[54] = ( ( TradeInformation.CardpPE[3] << 3 ) | ( recstat & 0x03 ) );
																//钱包类型,记录类型状态
	memcpy( &buf[55], TradeInformation.TTC, 4 );				//SAM交易流水号		

	buf[59] = TradeInformation.Mtype;												//主卡类型 0:公交，1:银联 10,瑞贝卡卡
	//buf[60] = DealCfg.DiscInfo[TradeInformation.CardTypeCout].CardType;
	buf[60] = CPU_CommInfo.CardType;
													   			//子卡类型 普通卡，老人卡等
	buf[61] = 0;												//卡内版本，没有使用写0
	buf[62] = 0x01;												//交易性质,公交，地铁等

	if( ( TradeInformation.CardpPE[3] == 3 ) || ( stat != 0 ) )	//次卡折扣金额为0 逃票记录没有折扣
	{ 
		buf[63] = 0;
		buf[64] = 0;
	}
	else
	{
		i = 0;
		if( TradeInformation.UnitPrice > TradeInformation.DealMoney )
		{ i = TradeInformation.UnitPrice - TradeInformation.DealMoney; }
		buf[63] = ( i >> 8 );
		buf[64] = i;						  					//折扣金额			
	}

	if( ( DealCfg.TimePriceStat != 0 ) || ( stat != 0 ) )		//分段收费模式 或逃票模式
	{
//		buf[63] = 0;
//		buf[64] = 0;											//分段收费模式，折扣金额为0
			
		if( stat != 0 )	
		{ memcpy( &buf[65], CPUM1_BillInfo.PsamTID, 6 ); }		//逃票POS编号	
		else
		{ memset( &buf[65], 0, 6 ); }	   						//正常
						
		buf[71] = CPUM1_BillInfo.UpID >> 8;						//上车站点编号
		buf[72] = CPUM1_BillInfo.UpID;							//上车站点编号
		if( stat != 0 )	
		{														//逃票情况固定为0
			buf[73] = 0;										//下车站点编号
			buf[74] = 0;										//下车站点编号				
		}
		else
		{
			buf[73] = ( 0 );				//下车站点编号
			buf[74] = 0;						//下车站点编号				
		}
	}
	else
	{
		memset( &buf[65], 0, 6 );								//逃票POS编号		
		memset( &buf[71], 0, 2 );								//上车站点编号
		memset( &buf[73], 0, 2 );								//下车站点编号		
	}
	
	if( recstat == 2 )											//灰记录TAC为0
	{ memset( TradeInformation.TAC, 0, 4 ); }
	memcpy( &buf[75], TradeInformation.TAC, 4 );				//TAC码

//=====================================>> 保存记录
	rcode = APP_Write_RecFile( id, buf );						//保存记录
	if( rcode != 0 )
	{
		ER_Pro:
		//错误处理
		DEF_SysCard_Debug;
	}	
}

U32 App_PSAM_Init( void )
{
	U32 rcode;
	//PSAM
	rcode = ICF_SelectSFI( "\x3F\x00", Gich_Sam );
    if( rcode != 0x9000 )
    { DEF_SysCard_Debug ;return rcode;}	
	rcode = ICF_ReadBinaryFile( 0x15, 0, 0, Gich_Sam );
	if(rcode != 0x9000)
	{ DEF_SysCard_Debug ;return rcode;}	
	CurCalc_DataCpy( gSamAppInfo.PsamASN, gpRcvBuffer, 10 ); 
	rcode = ICF_ReadBinaryFile( 0x16, 0, 0, Gich_Sam );
	if( rcode != 0x9000 )
	{ DEF_SysCard_Debug ;return rcode;}	
    CurCalc_DataCpy( gSamAppInfo.PsamTID, gpRcvBuffer, 6 ); 

    gSamAppInfo.PsamKeyIndex = 0x01; 

    //rcode = ICF_SelectSFI( (unsigned char*)"\x10\x01", Gich_Sam );
	//if( rcode != 0x9000 )
	//{ DEF_SysCard_Debug ;return rcode;}	

    return rcode;
}
U32 ICF_InitSamForPurchase_E( U08 *icc, 
                            U08 *CTC, 
							U08 *Amont, 
		                    U08 *CurrentTime, 
							U08 KeyVer, 
							U08 KeyDrk,
		                    U08 *ASN, 
							U08 *MakeCardId, 
							U32 ich )
{
	U32 rcode;

	gCmdBuffer[0] = 0x80;	//CLA
	gCmdBuffer[1] = 0x70;	//INS
	gCmdBuffer[2] = 0x00;	//P1
	gCmdBuffer[3] = 0x00;	//P2
	gCmdBuffer[4] = 0x24 ;	//Lc
	
	CurCalc_DataCpy(gCmdBuffer+5, icc,4);					//随机数    						 
	CurCalc_DataCpy(gCmdBuffer+9, CTC,2);					//脱机交易序号 						 
	CurCalc_DataCpy(gCmdBuffer+11, Amont,4);				//交易金额 									 
	gCmdBuffer[15] = 0x06;									//交易类型标识直接送#91H					 
	CurCalc_DataCpy(gCmdBuffer+16, CurrentTime,7);	    	//交易时间 										 
	gCmdBuffer[23] = KeyVer;								 
	gCmdBuffer[24] = KeyDrk;								//密钥算法标识 									 
	CurCalc_DataCpy(gCmdBuffer+25,ASN,8);					//卡号  注意，这里只使用后8位			 
	CurCalc_DataCpy(gCmdBuffer+33,MakeCardId,8);			//成员标识								 
	//gCmdBuffer[41] = 0x08;	//Le


	rcode = ICC_APDU_Exchange( ich, gCmdBuffer, 0x29, gpRcvBuffer, &Grcv_Len, 260 );
	if( rcode != 0 )
	{ return rcode; }

	if( Grcv_Len < 2 )
	{ return 2;}
	rcode = ( ( gpRcvBuffer[ Grcv_Len - 2 ] << 8 ) | gpRcvBuffer[ Grcv_Len - 1 ] );

	return rcode;
}

extern U32 ICF_ReadBinaryFile_all( U32 ich );
U32 Card_CPU_Check( void )
{
	U32 rcode = 0;
	U32 IcBackBalance;

	printf("Card_CPU_Check:\n");

	rcode = ICF_SelectSFI( "\x3F\x00", Gich_Sam );
	rcode = ICF_SelectAID( "\xBD\xA8\xC9\xE8\xB2\xBF", 6, Gich_Sam );
	if( rcode != 0x9000 )
	{
		DEF_SysCard_Debug;
		ICF_SelectAID( "\xBD\xA8\xC9\xE8\xB2\xBF", 6, Gich_Sam );
		if( rcode != 0x9000 )
		{ return 5;	}
	}
	
	
	rcode = ICF_SelectAID( "\xA0\x00\x00\x00\x03\x86\x98\x07\x01", 9, Gich_Icc ); //荆州 住建部
	if( rcode != 0x9000 ) 
	{
		DEF_SysCard_Debug;
		return 2;		
	}
	//读公共信息文件0015
	rcode =ICF_ReadBinaryFile(0x15, 0, 30, Gich_Icc);
	if( rcode != 0x9000 ) 
	{
		DEF_SysCard_Debug;
		//ICC_PCD_RadioOff(); 
		return 3;		
	}
	
	memcpy(TradeInformation.CardASN,&gpRcvBuffer[12],8);
	memcpy( TradeInformation.CityCode, &gpRcvBuffer[2], 2 );	 //城市代码 HEX
	rcode =ICF_ReadBinaryFile(22, 0, 51, Gich_Icc);
	if( rcode != 0x9000 ) 
	{
		DEF_SysCard_Debug;
		//ICC_PCD_RadioOff(); 
		return 3;		
	}
	// rcode =ICF_ReadBinaryFile(6, 0, 48, Gich_Icc);
	// if( rcode != 0x9000 ) 
	// {
		// DEF_SysCard_Debug;
		// //ICC_PCD_RadioOff(); 
		// return 3;		
	// }
	//===================================>>黑名单查找
	rcode = APP_ADV_FindBlacklist_cpu( TradeInformation.CardASN );
	if( rcode == 0 )
	{
	    Dis_Err_CardDis( 30, "黑卡,请投币" );	//黑卡
		DEF_SysCard_Debug;
		return 1;
	}
	// rcode = ICF_ReadRecord( 0x0B, 1, 4, Gich_Icc );
	// if( rcode != 0x9000 )
	// {
		// Dis_Err_CardDis( rcode, "读0B Fail");
		// DEF_SysCard_Debug;
		// return 4;
	// }
	//memcpy(&CPU_CommInfo.CounterSn[1], &gpRcvBuffer[1],3);
	//CPU_CommInfo.HolderCardSn = gpRcvBuffer[9];
	//TradeInformation.Mtype = 10;
	TradeInformation.CardpPE[3] = 1;
	
	rcode = ICF_GetBalanceEP( &IcBackBalance, Gich_Icc ); 
	if( rcode != 0x9000 )							 //一般读取ED余额需验证个人密码PIN 
	{
		DEF_SysCard_Debug;
		return 15;
	} 
	TradeInformation.OldPurseBalance = IcBackBalance;

	// if( memcmp( &gpRcvBuffer[20], TradeInformation.DealTime, 4 ) > 0 )
	// {														//启用期
	// 	Dis_Err_CardDis( 30, "请投币" );
	// 	DEF_SysCard_Debug;
	// 	return 1;	
	// }
				
	// if( memcmp( &gpRcvBuffer[24], TradeInformation.DealTime, 4 ) < 0 )
	// {														//停用期
	// 	Dis_Err_CardDis( 40, "请投币" );
	// 	DEF_SysCard_Debug;
	// 	return 1;	
	// }
	// memcpy( TradeInformation.CardASN, &gpRcvBuffer[12], 8 );//黑名单号


	// TradeInformation.CardpPE[3] = 1;					//强制使用电子现金钱包			

	return 0;
}
U32 Card_CPU_WaitInBusinessMoney( void )
{
	printf("Card_CPU_WaitInBusinessMoney:\n");
	TradeInformation.DealMoney = 0;
	return 0;
}
U32 Card_CPU_Exch( void )
{
	U32 rcode;
	U08 Temp[8],buf[20],Icc[4],PsamMAC1[4];	
	U08 KeyVer,KeyDrk;
	
	printf("Card_CPU_Exch:\n");
	
	memcpy( TradeInformation.LastCardPhySN, TradeInformation.CardPhySN, 12 );//暂存卡号


	rcode = ICF_GetSecuityCode( Gich_Icc );
	if( rcode != 0x9000 )							
	{
		DEF_SysCard_Debug;
		return 15;
	}
	memcpy( buf, gpRcvBuffer, 9 );
	rcode = ICF_CheckSecuityCode( buf, Gich_Sam );
	if( rcode != 0x9000 )							
	{
		DEF_SysCard_Debug;
	}
/*
*******************************************************************************
* 〖3〗消费初始化	                --> CPU	(电子存折)
*******************************************************************************
*/
	Temp[0] = ( TradeInformation.DealMoney >> 24 );
	Temp[1] = ( TradeInformation.DealMoney >> 16 );
	Temp[2] = ( TradeInformation.DealMoney >>  8 );
	Temp[3] = ( TradeInformation.DealMoney >>  0 );
    rcode = ICF_InitForPurchaseEP( gSamAppInfo.PsamKeyIndex, 
	                               Temp, 
								   gSamAppInfo.PsamTID, 
								   Gich_Icc );
	if( rcode != 0x9000 )									//初始化失败				 
	{
		DEF_SysCard_Debug;
		return rcode;
	}
//====================>> 保存相关信息
	memcpy( Temp, gpRcvBuffer, 4 );	 						//旧余额
	TradeInformation.OldPurseBalance =  ( Temp[0] * 0x1000000 ) + 
										( Temp[1] * 0x10000 ) 	+ 
										( Temp[2] * 0x100 ) 	+
										  Temp[3];
    memcpy( TradeInformation.PullCTC, gpRcvBuffer + 4, 2 );	//脱机交易序号
	Temp[0] = 0;
    memcpy( &Temp[1], gpRcvBuffer + 6, 3 );					//透支限额
	//TradeInformation.DebitLimt.Int32Bit = Temp[0]*0x1000000 + Temp[1]*0x10000 + Temp[2]*0x100 +Temp[3];
	KeyVer = *( gpRcvBuffer + 9 );     						//密钥版
	KeyDrk = *( gpRcvBuffer + 10 );							//算法标识
    memcpy( Icc, gpRcvBuffer + 11,4 );						//随机数
/*
*******************************************************************************
* 〖4〗选择PSAM卡 应用目录
*******************************************************************************
*/

/*
*******************************************************************************
* 〖5〗PSAM卡MAC1计算			    --> PSAM
*******************************************************************************
*/
 	//memcpy(TradeInformation.CityCode,"\x00\x00",2);
 	memcpy( Temp, TradeInformation.CityCode, 2 );
 	memset( &Temp[2], 0xFF, 6 );
 	memset( &Temp[3], 0, 5 );
 	buf[0] = ( TradeInformation.DealMoney >> 24 );			//交易金额  
 	buf[1] = ( TradeInformation.DealMoney >> 16 );			//交易金额 
 	buf[2] = ( TradeInformation.DealMoney >>  8 );			//交易金额  
 	buf[3] = ( TradeInformation.DealMoney >>  0 );			//交易金额 
 //====================>> 发送MAC1计算命令
 	rcode = ICF_InitSamForPurchase_E( Icc,					//随机数        
 	                                TradeInformation.PullCTC,		//脱机交易序号         
 									buf,							//交易金额  
 									TradeInformation.DealTime,		//当前时间   
 							        KeyVer,							//密钥版本  
 									KeyDrk,							//密钥算法标识 
 									TradeInformation.CardASN,		//卡片应用序列号 
 									Temp,							//成员标识  
 									Gich_Sam );				   		//通讯接口 
 	if( rcode != 0x9000 ) 
 	{
 		DEF_SysCard_Debug;
 		rcode = App_PSAM_Init();
 		if( rcode != 0x9000 )
 		{
 			Dis_Err_CardDis( 200, "" );
 			return 60;
 		}

 		rcode = ICF_InitSamForPurchase_E( Icc,						//随机数        
 		                            	TradeInformation.PullCTC,	//脱机交易序号         
 										buf,						//交易金额  
 										TradeInformation.DealTime,	//当前时间   
 								        KeyVer,						//密钥版本  
 										KeyDrk,						//密钥算法标识 
 										TradeInformation.CardASN,	//卡片应用序列号 
 										Temp,						//成员标识  
 										Gich_Sam );	
 		if( rcode != 0x9000 )		 
 		{
 			//Err_MAC1:
 			DEF_SysCard_Debug;
 			Dis_Err_CardDis( 210, "" );
 			return 60;
 		}
 	}
 //====================>> 保存MAC1值
 	memcpy( TradeInformation.TTC, gpRcvBuffer, 4 );		//终端交易序号  
 	memcpy( PsamMAC1, gpRcvBuffer+4, 4 );	//MAC1值  

 /*
 *******************************************************************************
 * 〖6〗对用户卡发送消费				--> CPU
 *******************************************************************************
 */
 //====================>> 初始化数据单元
 	memset( TradeInformation.TAC,  0, 4 );
 	memset( TradeInformation.MAC2, 0, 4 );
 //====================>> 发送消费命令，扣钱
 	rcode = ICF_DebitForPurchase( TradeInformation.TTC,		//终端交易序号   
 	                              TradeInformation.DealTime,//交易时间  
 								  PsamMAC1,					//MAC1值    
 								  Gich_Icc );				
 	if( rcode != 0x9000 )									//此条记录执行要65MS左右时间
 	{
 		DEF_SysCard_Debug;
 	}
 	else
 	{
 		memcpy( TradeInformation.TAC, gpRcvBuffer, 4 );  	//保存TAC码 交易成功返回 
 		memcpy( TradeInformation.MAC2, gpRcvBuffer+4, 4 );	//保存MAC2 	交易成功返回		
 	}

 	TradeInformation.NewPurseBalance = ( TradeInformation.OldPurseBalance - TradeInformation.DealMoney ); 
 
/*
*******************************************************************************
* 〖7〗MAC2验证					    --> PSAM
*******************************************************************************
*/
	//ProOK:
	if( memcmp( TradeInformation.MAC2,"\x00\x00\x00\x00", 4 ) != 0 )
	{ rcode = ICF_CreditSamForPurchase( TradeInformation.MAC2, Gich_Sam ); } 
	else
	{ rcode = 1; }
	if(rcode == 0x9000)
	{
		printf("---------------------------------------------------\r\n");
		printf("Consume Success!\n");
		printf("Trade Money:%d\n",TradeInformation.DealMoney);
		printf("Wallet Left:%d\n",TradeInformation.NewPurseBalance);
		printf("TAC:%02x%02x%02x%02x\n",TradeInformation.TAC[0],TradeInformation.TAC[1],TradeInformation.TAC[2],TradeInformation.TAC[3]);	
		printf("Time:%02x%02x%02x%02x%02x%02x%02x\n",TradeInformation.DealTime[0],TradeInformation.DealTime[1],TradeInformation.DealTime[2]
		,TradeInformation.DealTime[3],TradeInformation.DealTime[4],TradeInformation.DealTime[5],TradeInformation.DealTime[6]);
	
		//保存记录
		APP_WriteRec_CpuRec( DEF_RecMoryBank_Black01, ( ( rcode == 0x9000 ) ? 1 : 3 ), 0 );
																		   		//保存交易记录
		if( TradeInformation.CardpPE[3] == 3 )									//次卡钱包
		{ OthCfg.MotoCardNumCout++;	}											//司机卡当班次汇总
		else
		{
			OthCfg.MotoCardRecCout++;											//司机卡当班记录总数
			OthCfg.MotoCardRecMone += TradeInformation.DealMoney;		
		}

	}
	return rcode;
}

void testcard_cpu()
{
	
	U32 rcode = 0;
	printf("begin cpu card test:\n");
	get_time();
	//PSAM
	App_PSAM_Init();

	rcode = Card_CPU_Check();
	if( rcode != 0 )												
	{ goto END; }
	rcode = Card_CPU_WaitInBusinessMoney();
	if( rcode != 0 )												
	{ goto END; }
	rcode = Card_CPU_Exch();
	if( rcode != 0 )												
	{ goto END; }
    
    return;

	END:	
    printf("card test over!\n");
    
}
